In [1]:
import sys; sys.path.append('../..')
from puzzles import leet_puzzle
leet_puzzle('valid-number')
In [2]:
def is_number(input_string):
"""
Determine if the input_string is a valid number or not, for example:
>>> is_number("0.1")
True
>>> is_number("abc")
False
- Numbers in scientific notation are allowed.
- Only '.' as decimal point is accepted.
- No thousands separators are allowed.
:param input_string: The input string to check.
:return: True if input_string is a valid number, otherwise False.
"""
input_string = input_string.strip(' ')
if input_string in ('.', ''):
return False
input_string = input_string.lstrip('+-')
last_is_digit = False
had_decimal_point = False
had_e = False
last = len(input_string) - 1
for i, c in enumerate(input_string):
# process allowed non digit characters
if c == 'e':
# 'e' is only valid if it is not the last character
# there is only one occurence, and it must follow a digit
if i == last or had_e or not last_is_digit:
return False
had_e = True
elif c == '.':
# decimal point is only valid if we didn't already have
# a scientific notation character, and it is the only
# decimal point
if had_decimal_point or had_e:
return False
had_decimal_point = True
elif c in ('+', '-'):
# + / - is only valid when not the first character if
# it occurs as part of scientific notation.
if last_c != 'e':
return False
elif not c.isdigit():
return False
else:
last_is_digit = True
last_c = c
return True
def is_number_using_float(input_string):
try:
float(input_string)
except ValueError:
return False
return True
test_cases = [
"", "0", "0.1", " 0.1", "abc", "4e10", "4.5e10", "4.5e10e10",
"-4", "+4", " ", "...", ".0.0.0.", "1.abc", "e", "10e", "1e2",
".31", " . ", ".", "x.y.z", "2.4.6", ".1", "1.", "..1", "1..",
"6e6.6", "0042032e+6", "0042032e6+6", "+.1", "-1.", "..1", "1..",
"1+", "1-", "1 2 3 4 ", "1.2 3", ".1.2.3.", "_123", " e ", ".e",
"1,345,344.00"
]
for test_case in test_cases:
actual = is_number(test_case)
expected = is_number_using_float(test_case)
if actual != expected:
assert False, ('is_number("' + test_case + '") == ' +
str(actual) + ' != ' + str(expected))
print str(len(test_cases)) + ' tests passed'
In [3]:
%%timeit
is_number("0.34834")
In [4]:
%%timeit
is_number_using_float("0.34834")
The timings here demonstrate that it really isn't worth implementing your own float to string function. Best just used the build in conversion which probably uses optimised c code.